﻿using System;
using System.Globalization;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace Gmantis.Controls.DataGrid
{
    [TemplateVisualState(Name = "Selected", GroupName = "SelectionStates"), 
    TemplateVisualState(Name = "Unselected", GroupName = "SelectionStates"), 
    TemplateVisualState(Name = "Editing", GroupName = "SelectionStates"), 
    TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates"), 
    TemplateVisualState(Name = "Disabled", GroupName = "CommonStates"), 
    TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
    public class DataGridSelectableRowPresenter : DataGridRowPresenter
    {
        // Fields
        private bool _throwIsMouseOverChanged;
        internal static readonly DependencyProperty ForceMouseOverProperty = DependencyProperty.Register("ForceMouseOver", typeof(bool), typeof(DataGridSelectableRowPresenter), new PropertyMetadata(new PropertyChangedCallback(DataGridSelectableRowPresenter.OnForceMouseOverPropertyChanged)));
        public static readonly DependencyProperty IsEditingProperty = DependencyProperty.Register("IsEditing", typeof(bool), typeof(DataGridSelectableRowPresenter), new PropertyMetadata(new PropertyChangedCallback(DataGridSelectableRowPresenter.OnIsEditingPropertyChanged)));
        public static readonly DependencyProperty IsMouseOverProperty = DependencyProperty.Register("IsMouseOver", typeof(bool), typeof(DataGridSelectableRowPresenter), new PropertyMetadata(new PropertyChangedCallback(DataGridSelectableRowPresenter.OnIsMouseOverPropertyChanged)));
        public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(DataGridSelectableRowPresenter), new PropertyMetadata(new PropertyChangedCallback(DataGridSelectableRowPresenter.OnIsSelectedPropertyChanged)));
        public static readonly DependencyProperty MouseOverBrushProperty = DependencyProperty.Register("MouseOverBrush", typeof(Brush), typeof(DataGridSelectableRowPresenter), null);
        public static readonly DependencyProperty PressedBrushProperty = DependencyProperty.Register("PressedBrush", typeof(Brush), typeof(DataGridSelectableRowPresenter), null);
        public static readonly DependencyProperty SelectedBackgroundProperty = DependencyProperty.Register("SelectedBackground", typeof(Brush), typeof(DataGridSelectableRowPresenter), null);

        // Events
        public event EventHandler<PropertyChangedEventArgs<bool>> IsMouseOverChanged;

        // Methods
        public DataGridSelectableRowPresenter()
        {
            RoutedEventHandler handler = null;
            this._throwIsMouseOverChanged = true;
            base.DefaultStyleKey = typeof(DataGridSelectableRowPresenter);
            if (handler == null)
            {
                handler = delegate(object param0, RoutedEventArgs param1)
                {
                    this.ChangeVisualStateSelection(false);
                    this.ChangeVisualStateCommon(false);
                };
            }
            base.Loaded += handler;
            this.SetCustomDefaultValues();
        }

        protected void ChangeVisualStateCommon(bool useTransitions)
        {
            if (!base.IsEnabled)
            {
                VisualStateHelper.GoToState(this, "Disabled", useTransitions);
            }
            if (base.IsEnabled)
            {
                VisualStateHelper.GoToState(this, "MouseOver", useTransitions);
            }
            if ((base.IsEnabled && !this.IsMouseOver) && !this.ForceMouseOver)
            {
                VisualStateHelper.GoToState(this, "Normal", useTransitions);
            }
        }

        protected void ChangeVisualStateSelection(bool useTransitions)
        {
            if (this.IsSelected && this.IsEditing)
            {
                VisualStateHelper.GoToState(this, "Editing", useTransitions);
            }
            if (this.IsSelected && !this.IsEditing)
            {
                VisualStateHelper.GoToState(this, "Selected", useTransitions);
            }
            if (!this.IsSelected)
            {
                VisualStateHelper.GoToState(this, "Unselected", useTransitions);
            }
        }

        public override void OnApplyTemplate()
        {
            string str = string.Empty;
            base.OnApplyTemplate();
            if (!string.IsNullOrEmpty(str))
            {
                if ((base.Template != null) && !PlatformIndependent.IsInDesignMode(this))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Template cannot be applied to DataGridSelectableRowPresenter.\nDetails: {0}", new object[] { str }));
                }
            }
            else
            {
                this.ChangeVisualStateSelection(false);
                this.ChangeVisualStateCommon(false);
            }
        }

        private static void OnForceMouseOverPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as DataGridSelectableRowPresenter).ChangeVisualStateCommon(true);
        }

        private static void OnIsEditingPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as DataGridSelectableRowPresenter).ChangeVisualStateSelection(true);
        }

        private static void OnIsMouseOverPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataGridSelectableRowPresenter sender = d as DataGridSelectableRowPresenter;
            if ((sender.IsMouseOverChanged != null) && sender._throwIsMouseOverChanged)
            {
                PropertyChangedEventArgs<bool> args = new PropertyChangedEventArgs<bool>
                {
                    OldValue = (bool)e.OldValue,
                    NewValue = (bool)e.NewValue
                };
                sender.IsMouseOverChanged(sender, args);
            }
            sender.ChangeVisualStateCommon(true);
        }

        private static void OnIsSelectedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as DataGridSelectableRowPresenter).ChangeVisualStateSelection(true);
        }

        protected override void OnMouseEnter(MouseEventArgs e)
        {
            if ((base.View != null) && !base.Row.IsMouseOver)
            {
                base.View.SetMouseOverRow(base.Row);
            }
        }

        protected override void OnMouseLeave(MouseEventArgs e)
        {
            if (base.View != null)
            {
                base.View.ClearMouseOver();
            }
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonDown(e);
        }

        private void SetCustomDefaultValues()
        {
        }

        public override void UpdateEditingRow()
        {
            if (base.Row != null)
            {
                this.IsEditing = base.Row.IsEditing;
            }
        }

        public override void UpdateMouseOver()
        {
            base.UpdateMouseOver();
            if (base.Row != null)
            {
                this.ForceMouseOver = base.Row.IsMouseOver;
            }
        }

        public override void UpdateSelection()
        {
            base.UpdateSelection();
            if (base.Row != null)
            {
                this.IsSelected = base.Row.IsSelected;
            }
        }

        // Properties
        internal bool ForceMouseOver
        {
            get
            {
                return (bool)base.GetValue(ForceMouseOverProperty);
            }
            set
            {
                base.SetValue(ForceMouseOverProperty, value);
            }
        }

        public bool IsEditing
        {
            get
            {
                return (bool)base.GetValue(IsEditingProperty);
            }
            set
            {
                base.SetValue(IsEditingProperty, value);
            }
        }

        public bool IsMouseOver
        {
            get
            {
                return (bool)base.GetValue(IsMouseOverProperty);
            }
            internal set
            {
                base.SetValue(IsMouseOverProperty, value);
            }
        }

        public bool IsSelected
        {
            get
            {
                return (bool)base.GetValue(IsSelectedProperty);
            }
            set
            {
                base.SetValue(IsSelectedProperty, value);
            }
        }

        public Brush MouseOverBrush
        {
            get
            {
                return (Brush)base.GetValue(MouseOverBrushProperty);
            }
            set
            {
                base.SetValue(MouseOverBrushProperty, value);
            }
        }

        public Brush PressedBrush
        {
            get
            {
                return (Brush)base.GetValue(PressedBrushProperty);
            }
            set
            {
                base.SetValue(PressedBrushProperty, value);
            }
        }

        public Brush SelectedBackground
        {
            get
            {
                return (Brush)base.GetValue(SelectedBackgroundProperty);
            }
            set
            {
                base.SetValue(SelectedBackgroundProperty, value);
            }
        }
    }
}
